package kz.pompei.ifacer.visio.def.paint.grid;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;

import javax.swing.JComponent;

import kz.pompei.ifacer.cursor_manager.def.DefRectGeo;
import kz.pompei.ifacer.dialogs.TextAreaDialog;
import kz.pompei.ifacer.grot.acts.Act;
import kz.pompei.ifacer.grot.acts.ChangeFieldsAct;
import kz.pompei.ifacer.model.CursorInfo;
import kz.pompei.ifacer.model.CursorKind;
import kz.pompei.ifacer.model.PaintKind;
import kz.pompei.ifacer.model.widgets.WidgetGrid;
import kz.pompei.ifacer.visio.PaintUtil;
import kz.pompei.ifacer.visio.def.paint.grid.Grid.Row;
import kz.pompei.ifacer.visio.def.paint.grid.Grid.RowType;

public class PaintWidgetGrid {
  
  private final Grid grid = new Grid();
  
  private static final int ROW_HEIGHT = 23;
  private static final int TEXT_UP = 8;
  private static final int TEXT_RI = 3;
  
  public void
      paint(Graphics2D g, WidgetGrid w, PaintKind paintKind, Point mouse, Rectangle allSpace) {
    grid.assign(w);
    
    if (paintKind != PaintKind.MOVING) {
      g.setColor(Color.WHITE);
      g.fillRect(w.x, w.y, w.width, w.height);
    }
    
    Rectangle place = w.rect().intersection(allSpace);
    
    int yOffset = 0;
    for (int j = 0, Cj = grid.rows.size(); j < Cj && yOffset < w.height; j++) {
      Row row = grid.rows.get(j);
      int cellHeight = ROW_HEIGHT;
      Color textColor = new Color(0x1B324D);
      
      {
        Rectangle z = new Rectangle();
        z.x = w.x + 1;
        z.y = w.y + yOffset + 1;
        z.width = w.width - 1;
        z.height = cellHeight;
        z = z.intersection(place);
        Graphics2D g2 = (Graphics2D)g.create();
        g2.setClip(z.x, z.y, z.width, z.height);
        if (row.type == RowType.HEAD) {
          g2.setColor(new Color(0xBFBFBF));
          g2.drawLine(w.x, w.y + yOffset + cellHeight, w.x + w.width, w.y + yOffset + cellHeight);
          if (paintKind != PaintKind.MOVING) {
            PaintUtil.drawRectVert(g2, w.x + 1, w.y + yOffset + 1, w.width - 2, cellHeight - 1,
                new Color(0xFBFBFB), new Color(0xE8E8E8));
          }
        }
        if (row.type == RowType.SEL) {
          g2.setColor(new Color(0x82A8D6));
          //g2.drawLine(w.x, w.y + yOffset + cellHeight, w.x + w.width, w.y + yOffset + cellHeight);
          if (paintKind != PaintKind.MOVING) {
            g2.fillRect(w.x + 1, w.y + yOffset + 1, w.width - 2, cellHeight - 1);
          }
          textColor = Color.BLUE;
        }
        if (row.type == RowType.NORMAL || row.type == RowType.SEL) {
          g2.setColor(new Color(0xBFBFBF));
          g2.drawLine(w.x, w.y + yOffset + cellHeight, w.x + w.width, w.y + yOffset + cellHeight);
        }
        
        g2.dispose();
      }
      int xOffset = 0;
      for (int i = 0, Ci = grid.colCount(); i < Ci; i++) {
        int cellWidth = grid.getColWidth(i);
        if (i == Ci - 1) {
          cellWidth = w.width - xOffset;
        }
        int right = xOffset + cellWidth;
        {
          Graphics2D g2 = (Graphics2D)g.create();
          
          Rectangle cell = new Rectangle();
          cell.x = w.x + xOffset + 1;
          cell.y = w.y + yOffset + 1;
          cell.width = cellWidth - 1;
          cell.height = cellHeight - 1;
          cell = cell.intersection(place);
          
          if (row.type != RowType.SEL) {
            g2.setColor(new Color(0xCCCCCC));
            int y2 = cell.y + cellHeight;
            if (y2 > w.y + w.height) y2 = w.y + w.height;
            g2.drawLine(cell.x + cell.width, cell.y, cell.x + cell.width, y2);
          }
          
          g2.setColor(Color.WHITE);
          if (row.type != RowType.SEL) {
            g2.drawLine(cell.x, cell.y, cell.x, cell.y + cellHeight);
          }
          g2.setClip(cell.x, cell.y, cell.width, cell.height);
          
          g2.setColor(paintKind == PaintKind.MOVING ? Color.GRAY :textColor);
          row.get(i).draw(g2, cell.x + TEXT_RI, cell.y + cellHeight - TEXT_UP,
              row.type != RowType.SEL && paintKind != PaintKind.MOVING);
          g2.dispose();
        }
        if (xOffset < w.width) {
          xOffset = right;
          continue;
        }
        break;
      }
      yOffset += ROW_HEIGHT;
    }
    
    {
      Graphics2D g2 = (Graphics2D)g.create();
      g2.setColor(new Color(0xBFBFBF));
      float dash1[] = { 3.0f, 1f };
      BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
          10.0f, dash1, 0.0f);
      g2.setStroke(dashed);
      int offset = 0;
      for (int i = 0, C = grid.colCount() - 1; i < C && offset < w.width; i++) {
        offset += grid.getColWidth(i);
        g2.drawLine(w.x + offset, w.y, w.x + offset, w.y + w.height);
      }
      g2.dispose();
      grid.colCount();
    }
    {
      g.setColor(paintKind.isOver() ? Color.BLACK :new Color(0xABABAB));
      g.drawRect(w.x, w.y, w.width, w.height);
    }
    if (paintKind.isSel()) {
      PaintUtil.drawSelectionRect(g, w.x, w.y, w.width, w.height);
    }
  }
  
  public CursorInfo getCursorInfo(Graphics2D g, WidgetGrid w, Point mouse) {
    
    //hit border
    {
      CursorKind cursorKind = getBorderCursor(w, mouse);
      if (cursorKind != null) {
        return new CursorInfo(cursorKind, null);
      }
    }
    
    //hit resize of column
    {
      CursorKind cursorKind = getColResizeIndex(w, mouse) < 0 ? null :CursorKind.RESIZE_HOR;
      if (cursorKind != null) {
        return new CursorInfo(cursorKind, null);
      }
    }
    
    //hit body
    if (new Rectangle(w.x, w.y, w.width, w.height).contains(mouse)) {
      CursorInfo ret = new CursorInfo(CursorKind.MOVE, "EDIT");
      return ret;
    }
    
    //missed
    return null;
  }
  
  private CursorKind getBorderCursor(WidgetGrid f, Point point) {
    return DefRectGeo.cursorKindOnBorder(point, f, PaintUtil.BORDER_WIDTH, PaintUtil.CORNER_SIZE);
  }
  
  public Act move(Graphics2D g, WidgetGrid original, WidgetGrid copy, Point from, Point to)
      throws Exception {
    
    int dx = to.x - from.x;
    int dy = to.y - from.y;
    
    {
      int col = getColResizeIndex(original, from);
      if (col >= 0) return resizeColumn(col, dx, original, copy);
    }
    
    {
      CursorKind borderCursor = getBorderCursor(original, from);
      if (borderCursor == null) borderCursor = CursorKind.MOVE;
      return PaintUtil.resize(dx, dy, borderCursor, original, copy);
    }
  }
  
  private Act resizeColumn(int col, int dx, WidgetGrid from, WidgetGrid to) {
    grid.assign(from);
    int newWidth = grid.getColWidth(col) + dx;
    if (newWidth < 10) newWidth = 10;
    grid.setColWidth(col, newWidth);
    to.widths = grid.getWidths();
    return new ChangeFieldsAct(from.uuid, "widths", grid.getWidths());
  }
  
  private static final int K = 2;
  
  private int getColResizeIndex(WidgetGrid w, Point mouse) {
    grid.assign(w);
    
    if (mouse.y < w.y) return -1;
    if (mouse.y > w.y + w.height) return -1;
    
    int x = w.x;
    for (int i = 0, C = grid.colCount() - 1; i < C; i++) {
      x += grid.getColWidth(i);
      if (mouse.x < x - K) return -1;
      if (mouse.x < x + K) return i;
    }
    
    return -1;
  }
  
  public Act getDoubleClickAct(Graphics2D g, WidgetGrid w, Point mouse, JComponent owner)
      throws Exception {
    
    String res = TextAreaDialog.show(owner, w.contents, w.x, w.y);
    if (res == null) return null;
    
    return new ChangeFieldsAct(w.uuid, "contents", res);
  }
  
  public Rectangle getWidgetBound(Graphics2D g, WidgetGrid f) {
    return f.rect();
  }
  
}
